package com.dxm.common.utils;

import com.alibaba.fastjson.JSONObject;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.X509Certificate;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

@Slf4j
public class DxmUtil {

    //添加主机名验证程序类，设置不验证主机
    private final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    //添加信任主机
    private static void trustAllHosts() {
        // 创建不验证证书链的信任管理器 这里使用的是x509证书
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[]{};
            }

            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {
            }
        }};
        // 安装所有信任的信任管理器
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            //HttpsURLConnection通过SSLSocket来建立与HTTPS的安全连接，SSLSocket对象是由SSLSocketFactory生成的。
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

//    //这里可以用main方法测试
//    public static void main(String[] args) throws Exception {
//        Map<String, String> params = new HashMap<>();
//        params.put("firstName", "Mickey");
//        params.put("lastName", "Mouse");
//        //要发送的POST请求url?Key=Value&amp;Key2=Value2&amp;Key3=Value3的形式
//        //application/json;charset=UTF-8  application/x-www-form-urlencoded;charset=UTF-8
//        send("https://localhost:8888/tests",map2Url(params),"application/x-www-form-urlencoded;charset=UTF-8","POST","1","1", AESUtil8.generateKey());
//    }

    /**
     * 发送post 数据
     *
     * @param urls
     * @return
     */
    public static String sendPost(String urls, Map<String, String> paramMap) {
        StringBuffer sb = new StringBuffer();
        DataOutputStream out = null;
        BufferedReader responseReader = null;
        InputStream in1 = null;
        try {
            trustAllHosts();
            // 创建url资源
            URL url = new URL(urls);
            // 建立http连接
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setHostnameVerifier(DO_NOT_VERIFY);
            // 设置不用缓存
            conn.setUseCaches(false);
            // 设置允许输出
            conn.setDoOutput(true);
            // 设置允许输入
            conn.setDoInput(true);
            // 设置传递方式
            conn.setRequestMethod("POST");
            //System.out.println(conn.getRequestMethod());
            // 设置维持长连接
            conn.setRequestProperty("Connection", "Keep-Alive");
            // 设置文件字符集:
            conn.setRequestProperty("Charset", "UTF-8");
            // 转换为字节数组
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
            //设置接入方渠道号:
            conn.setRequestProperty("channel", paramMap.get("channel"));
            //设置接口的版本号，必须为1:
            conn.setRequestProperty("version", paramMap.get("version"));
            //设置签名结果:
            conn.setRequestProperty("sign", paramMap.get("sign"));
            // 开始连接请求
            conn.connect();
            out = new DataOutputStream(conn.getOutputStream());
            // 写入请求的字符串
            log.info("dxm send param:{}", paramMap);
            paramMap.remove("channel");
            paramMap.remove("version");
            paramMap.remove("sign");
            paramMap.remove("key");
            String data = map2Url(paramMap);
            out.writeBytes(data);
            out.flush();
            // 请求返回的状态
            if (HttpURLConnection.HTTP_OK == conn.getResponseCode()) {
                // 请求返回的数据
                in1 = conn.getInputStream();
                String readLine;
                responseReader = new BufferedReader(new InputStreamReader(in1, "UTF-8"));
                while ((readLine = responseReader.readLine()) != null) {
                    sb.append(readLine).append("\n");
                }
                String result = sb.toString();
                result = DecodeUtil.decodeUnicode(result);
                log.info("请求度小满接口返回数据：{}", result);
                return result;
            }
        } catch (Exception e) {
            log.error("dxm send error.", e);
        } finally {
            try {
                if (null != responseReader) {
                    responseReader.close();
                }
                if (null != in1) {
                    in1.close();
                }
            } catch (Exception e) {
            }
            try {
                out.close();
            } catch (Exception e) {
            }
        }
        return "{}";
    }

    /**
     * 发送get 数据
     *
     * @param urls
     * @return
     */
    public static String sendGet(String urls, String param, String contentType) {
        StringBuffer sb = new StringBuffer();
        DataOutputStream out = null;
        BufferedReader responseReader = null;
        InputStream in1 = null;
        try {
            trustAllHosts();
            // 创建url资源
            URL url = new URL(urls + "?" + param);
            // 建立http连接
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setHostnameVerifier(DO_NOT_VERIFY);
            // 设置不用缓存
            conn.setUseCaches(false);
            // 设置允许输出
            conn.setDoOutput(true);
            // 设置允许输入
            conn.setDoInput(true);
            // 设置传递方式
            conn.setRequestMethod("GET");
            System.out.println(conn.getRequestMethod());
            // 设置维持长连接
            conn.setRequestProperty("Connection", "Keep-Alive");
            // 设置文件字符集:
            conn.setRequestProperty("Charset", "UTF-8");
            // 转换为字节数组
//            byte[] data = (param).getBytes();
//            // 设置文件长度
//            conn.setRequestProperty("Content-Length", String.valueOf(data.length));
            // 设置文件类型:
            conn.setRequestProperty("Content-Type", contentType);
            // 开始连接请求
            conn.connect();
//            out = new DataOutputStream(conn.getOutputStream());
//            // 写入请求的字符串
//            out.writeBytes(param);
//            out.flush();

            System.out.println(conn.getResponseCode());

            // 请求返回的状态
            if (HttpURLConnection.HTTP_OK == conn.getResponseCode()) {
                System.out.println("连接成功");
                // 请求返回的数据
                in1 = conn.getInputStream();
                String readLine;
                responseReader = new BufferedReader(new InputStreamReader(in1, "UTF-8"));
                while ((readLine = responseReader.readLine()) != null) {
                    sb.append(readLine).append("\n");
                }
            } else {
                System.out.println("error++");
            }
        } catch (Exception e) {

        } finally {
            try {
                if (null != responseReader) {
                    responseReader.close();
                }
                if (null != in1) {
                    in1.close();
                }
            } catch (Exception e) {
            }
            try {
                out.close();
            } catch (Exception e) {
            }
        }

        return sb.toString();

    }

    /**
     * map转url参数
     */
    public static String map2Url(Map<String, String> paramToMap) {
        if (null == paramToMap || paramToMap.isEmpty()) {
            return "";
        }
        StringBuffer url = new StringBuffer();
        for (Map.Entry<String, String> entry : paramToMap.entrySet()) {
            if (url.length() > 0) {
                url.append("&");
            }
            String value = entry.getValue();
            if (!StringUtils.isEmpty(value)) {
                try {
                    url.append(entry.getKey()).append("=").append(URLEncoder.encode(value, "UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        }
        return url.toString();
    }
    /**
     * map转url参数(不用转码)
     */
    public static String map2UrlNoEncoder(Map<String, String> paramToMap) {
        if (null == paramToMap || paramToMap.isEmpty()) {
            return "";
        }
        StringBuffer url = new StringBuffer();
        for (Map.Entry<String, String> entry : paramToMap.entrySet()) {
            if (url.length() > 0) {
                url.append("&");
            }
            String value = entry.getValue();
            if (!StringUtils.isEmpty(value)) {
                url.append(entry.getKey()).append("=").append(value);
            }
        }
        return url.toString();
    }

    public static boolean checkSign(JSONObject data, String token) {
        String sign = data.remove("sign").toString();
        return sign.equals(sign(sortMapByKey(data), token));
    }

    private static Map<String, String> sortMapByKey(JSONObject map) {
        //treeMap适用于按自然顺序或自定义顺序遍历键(key)
        Map<String, String> treeMap = new TreeMap<>(Comparator.comparing(k->k));
        map.forEach((k, v)->treeMap.put(k, v.toString()));
        return treeMap;
    }


    public static String sign(Map<String, String> paramMap, String token) {
        paramMap.put("key", token);
        String signData = DxmUtil.map2UrlNoEncoder(paramMap);
        String sign = MD5Util.md5(signData);
        log.info("dxm sign data:{}, sign:{}", signData, sign);
        return sign;
    }


}
